/*
 * This source code is part of TWaver 4.0
 *
 * Serva Software PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 * Copyright 2002 - 2011 Serva Software. All rights reserved.
 */

package demo.network.topo.performance;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

import twaver.Element;
import twaver.Link;
import twaver.ResizableNode;
import twaver.TDataBox;
import twaver.TWaverConst;
import twaver.TWaverUtil;
import twaver.Node;
import twaver.swing.LabelValueLayout;
import demo.DemoUtil;

public class OperationPane extends JPanel {
    private JTabbedPane tab = new JTabbedPane();
    private TDataBox box = null;
    private JTextArea information = DemoUtil.createColorTextArea();
    private boolean stop = true;
    final JLabel inforLabel = new JLabel();
    
    private synchronized void setStop(boolean value) {
        stop = value;
    }

    private synchronized boolean isStop() {
        return stop;
    }

    public OperationPane(final TDataBox box) {
        this.box = box;
        this.setLayout(new BorderLayout());
        this.add(tab, BorderLayout.NORTH);
        
        JPanel inforPane = new JPanel(new BorderLayout());

        inforPane.add(new JScrollPane(information), BorderLayout.CENTER);
        inforPane.add(inforLabel, BorderLayout.NORTH);
        this.add(inforPane, BorderLayout.CENTER);
        
        inforLabel.setHorizontalAlignment(JLabel.CENTER);
        this.updateLabel();
        this.initPane();
    }

	private void updateLabel(){
		inforLabel.setText("<html>Total Element Count: <font color=red>" + box.size() + "</font></html>");
	}
    
    private void initPane() {
        JPanel pane = new JPanel(new LabelValueLayout(true));

        //element location bounds
        pane.add(new JLabel("Location X Limit:"));
        final JTextField txtLimitX = new JTextField("1000");
        pane.add(txtLimitX);
        pane.add(new JLabel("Location Y Limit:"));
        final JTextField txtLimitY = new JTextField("1000");
        pane.add(txtLimitY);

        pane.add(new JSeparator());
        pane.add(new JLabel(""));

        pane.add(new JLabel("Node Count:"));
        final JTextField txtNodeCount = new JTextField("1000");
        pane.add(txtNodeCount);
        pane.add(new JLabel("Link Count:"));
        final JTextField txtLinkCount = new JTextField("50");
        pane.add(txtLinkCount);
        pane.add(new JLabel("Alarm Proportion"));
        final JSlider alarmProportion = new JSlider(0, 100, 10);
        pane.add(alarmProportion);
        
        pane.add(new JLabel(""));
        final JCheckBox cbImage = new JCheckBox("Use  Image Icon");
        pane.add(cbImage);

        pane.add(new JLabel(""));
        JButton btnCreateElement = new JButton();
        btnCreateElement.setHorizontalAlignment(SwingConstants.LEADING);
        btnCreateElement.setText("Create Elements");
        pane.add(btnCreateElement);
        btnCreateElement.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
					int nodeCount = Integer.valueOf(txtNodeCount.getText()).intValue();
					int linkCount = Integer.valueOf(txtLinkCount.getText()).intValue();
					boolean useIcon = cbImage.isSelected();
					int xLimit = Integer.valueOf(txtLimitX.getText()).intValue();
					int yLimit = Integer.valueOf(txtLimitY.getText()).intValue();
					testElement(nodeCount, linkCount, useIcon, xLimit, yLimit);
                }catch(Exception ex){
                	information.append(ex.getMessage());
                }
            }
        });

        pane.add(new JLabel(""));
        JButton btnAlarm = new JButton();
        btnAlarm.setHorizontalAlignment(SwingConstants.LEADING);
        btnAlarm.setText("Create Alarms");
        pane.add(btnAlarm);
        btnAlarm.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                testAlarm(alarmProportion.getValue()/100.0);
            }
        });

        pane.add(new JLabel(""));
        JButton btnClearAlarm = new JButton();
        btnClearAlarm.setHorizontalAlignment(SwingConstants.LEADING);
        btnClearAlarm.setText("Clear Alarms");
        pane.add(btnClearAlarm);
        btnClearAlarm.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                testClearAlarm();
            }
        });

        pane.add(new JLabel(""));
        JButton btnClear = new JButton();
        btnClear.setHorizontalAlignment(SwingConstants.LEADING);
        btnClear.setText("Clear DataBox");
        pane.add(btnClear);
        btnClear.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                double time1 = System.currentTimeMillis();
                box.clear();
                double time2 = System.currentTimeMillis();
                double time = time2 - time1;
                information.append("Clear DataBox in " + time/1000 + " s.");
                updateLabel();
            }
        });

        pane.add(new JSeparator());
        pane.add(new JLabel(""));

        pane.add(new JLabel("Inteval (millisecond):"));
        final JTextField txtInteval = new JTextField("1000");
        pane.add(txtInteval);
        final JButton btnStart = new JButton("Start", TWaverUtil.getIcon("/demo/network/topo/performance/start.png"));
        btnStart.setHorizontalAlignment(JButton.LEFT);
        pane.add(new JLabel(""));
        pane.add(btnStart);
        
        btnStart.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            	btnStart.setEnabled(false);
                
                Thread thread = new Thread() {
                    public void run() {                   	
                        setStop(false);
                        
                        while (true) {
                        	int interval = 1000;
                            try{
                            	interval = Integer.valueOf(txtInteval.getText()).intValue();
                            }catch(Exception ex){
                            	information.append(ex.getMessage());
                            }
                        	
                            Runnable runCreate = new Runnable() {
                                public void run() {
                                    box.clear();
                                    try{
                                        int nodeCount = Integer.valueOf(txtNodeCount.getText()).intValue();
                                        int linkCount = Integer.valueOf(txtLinkCount.getText()).intValue();
                                        boolean useIcon = cbImage.isSelected();
                                        int xLimit = Integer.valueOf(txtLimitX.getText()).intValue();
                                        int yLimit = Integer.valueOf(txtLimitY.getText()).intValue();
                                        testElement(nodeCount, linkCount, useIcon, xLimit, yLimit);
                                    }catch(Exception ex){
                                    	information.append(ex.getMessage());
                                    }
                                }
                            };
                            Runnable runAlarm = new Runnable() {
                                public void run() {
                                	testAlarm(alarmProportion.getValue()/100.0);
                                }
                            };
                            Runnable runClearAlarm = new Runnable() {
                                public void run() {
                                    testClearAlarm();
                                }
                            };
                            Runnable runClear = new Runnable() {
                                public void run() {
                                    box.clear();
                                }
                            };

                            try {
                                //test create elements.
                                SwingUtilities.invokeAndWait(runCreate);
                                if (isStop())break;
                                Thread.sleep(interval);

                                //test create alarm for all elements.
                                SwingUtilities.invokeAndWait(runAlarm);
                                if (isStop())break;
                                Thread.sleep(interval);

                                //test clear all alarms for all elements.
                                SwingUtilities.invokeAndWait(runClearAlarm);
                                if (isStop())break;
                                Thread.sleep(interval);

                                //test clear all elements from data box.
                                SwingUtilities.invokeAndWait(runClear);
                                if (isStop())break;
                                Thread.sleep(interval);
                              
                                if(information.getLineCount() > 300){
                                	information.setText(null);
                                }
                            }
                            catch (Exception ex) {
                            	information.append(ex.getMessage());
                            }
                        }
                        
                        btnStart.setEnabled(true);
                    }
                };
                thread.start();
            }
        });

        final JButton btnStop = new JButton("Stop", TWaverUtil.getIcon("/demo/network/topo/performance/stop.png"));
        btnStop.setHorizontalAlignment(JButton.LEFT);
        pane.add(new JLabel(""));
        pane.add(btnStop);
        btnStop.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setStop(true);
            }
        });
        
        tab.addTab("Control Panel", pane);
    }

    private void testElement(int nodeCount, int linkCount, boolean useIcon, int xLimit, int yLimit) {
        List allNodes = new ArrayList(nodeCount);
        
        double time1 = System.currentTimeMillis();
        for (int i = 0; i < nodeCount; i++) {
            Node node = null;
            if (useIcon) {
                node = new Node();
            } else {
                node = new ResizableNode();
                ((ResizableNode) node).setSize(12, 12);
                node.putCustomDraw(true);
                node.putCustomDrawShapeFactory(TWaverConst.SHAPE_CIRCLE);
                node.putCustomDrawFillColor(Color.GREEN);
                node.putCustomDrawOutline(false);
                node.putBorderColor(Color.WHITE);
                node.putCustomDrawGradientFactory(TWaverConst.GRADIENT_RADIAL_NW);
            }

            int x = TWaverUtil.getRandomInt(xLimit);
            int y = TWaverUtil.getRandomInt(yLimit);

            node.setLocation(x, y);
            box.addElement(node);
            allNodes.add(node);
        }

        for (int i = 0; i < linkCount; i++) {
            Node node1 = (Node)allNodes.get(TWaverUtil.getRandomInt(nodeCount));
            Node node2 = (Node)allNodes.get(TWaverUtil.getRandomInt(nodeCount));
            
            Link link = new Link(node1, node2);
            link.putLinkWidth(0);
            link.putLinkOutlineWidth(0);
            link.putLinkColor(Color.YELLOW);
            link.putBorderColor(Color.WHITE);
            box.addElement(link);
        }

        double time2 = System.currentTimeMillis();
        double time = time2 - time1;
        information.append("Create " + nodeCount + " nodes and " + linkCount + " links in " + time/1000 + " s.");
        updateLabel();
    }

    private void testAlarm(double alarmProportion) {
        double time1 = System.currentTimeMillis();
        
        double i=1;
        Iterator it = box.iterator();
        while (it.hasNext()) {
            if(i/box.size() > alarmProportion){
            	break;
            }
        	Element element = (Element)it.next();
            element.getAlarmState().addNewAlarm(TWaverUtil.getRandomNonClearedSeverity());            
            i++;
        }
        
        double time2 = System.currentTimeMillis();
        double time = time2 - time1;
        information.append("Create alarms in " + time/1000 + " s.");
        updateLabel();
    }

    private void testClearAlarm() {
        double time1 = System.currentTimeMillis();
        Iterator it = box.iterator();
        while (it.hasNext()) {
            Element element = (Element)it.next();
            element.getAlarmState().clear();
        }

        double time2 = System.currentTimeMillis();
        double time = time2 - time1;
        information.append("Clear alarms in " + time/1000 + " s.");
        updateLabel();
    }
}